iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 20
0
自我挑戰組

寫遊戲初體驗系列 第 20

Day 20 Renderer 2D

  • 分享至 

  • xImage
  •  

Renderer2D

之前座標的文章中,明白投影矩陣的作用是把觀察空間坐標轉化為標準化設備坐標。

我們要 2D 的 renderer,所以用正射投影矩阵(Orthographic Projection Matrix)就可以了

glm::mat4 projection = glm::ortho(0.0f, width_, height_, 0.f, -1.0f, 1.0f);

Shader

我們要渲染東西,Shader 當然不可少囉。

  • VertexShader

    #version 330 core
    
    layout(location = 0) in vec3 a_Position;
    layout(location = 1) in vec2 a_TexCoord;
    
    out vec2 v_TexCoord;
    
    uniform mat4 transform;
    uniform mat4 projection;
    
    void main()
    {
        gl_Position = projection * transform * vec4(a_Position, 1.0);
        v_TexCoord = a_TexCoord;
    }
    
  • fragmentShader

    #version 330 core
    
    layout(location = 0) out vec4 color;
    
    in vec2 v_TexCoord;
    uniform sampler2D u_Texture;
    uniform vec4 ourColor;
    
    void main()
    {
        color = ourColor * texture(u_Texture, v_TexCoord);
    }
    

SpriteRenderer

為了讓渲染更有條理,我們定義一個SpriteRenderer的 class。

class SpriteRender {

public:
    SpriteRender() = default;
    SpriteRender(const std::shared_ptr<Shader>& shader);
    ~SpriteRender();

    void Draw(std::shared_ptr<Texture2D>& texture, glm::vec2 pos, glm::vec2 size, float rotate = 0.0f, glm::vec4 color = glm::vec4(1.0f));

private:

    std::shared_ptr<Shader> shader_;
    std::shared_ptr<VertexArray> vertexArray_;

    void Init();
};

初始化

void SpriteRender::Init() {

    float vertices[5 * 4] = {
            //     ---- 位置 ----
             0.5f,  0.5f, 0.0f, 1.0f, 1.0f,
             0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
            -0.5f, -0.5f, 0.0f, 0.0f, 0.0f,
            -0.5f,  0.5f, 0.0f, 0.0f, 1.0f
    };

    uint32_t indices[2 * 3] = {
            0, 1, 3,
            1, 2, 3
    };

    vertexArray_ = std::make_shared<VertexArray>();
    std::shared_ptr<VertexBuffer> vertexBuffer;
    vertexBuffer = std::make_shared<VertexBuffer>(vertices, sizeof(vertices));

    BufferLayout layout = {
        {ShaderDataType::Float3, "a_Position"},
        {ShaderDataType::Float2, "a_TexCoord"}};

    vertexBuffer->setLayout(layout);
    vertexArray_->addVertexBuffer(vertexBuffer);
    std::shared_ptr<IndexBuffer> indexBuffer;
    indexBuffer = std::make_shared<IndexBuffer>(indices, sizeof(indices) / sizeof(uint32_t));

    vertexArray_->setIndexBuffer(indexBuffer);

    vertexArray_->unbind();
}

Draw

void SpriteRender::Draw(std::shared_ptr<Texture2D>& texture, glm::vec2 pos, glm::vec2 size, float rotate, glm::vec4 color) {

    texture->bind();
    shader_->bind();
    shader_->setFloat4("ourColor", color);
    glm::mat4 transform(1.0f);
    transform = glm::translate(transform, glm::vec3(pos, 0.0));

    transform = glm::translate(transform, glm::vec3(0.5f*size.x, 0.5*size.y, 0.0f));
    transform = glm::rotate(transform, rotate, glm::vec3(0.0f, 0.0f, 1.0f));
    transform = glm::translate(transform, glm::vec3(-0.5f*size.x, -0.5f*size.y, 0.0f));

    // transform = glm::translate(transform, glm::vec3(0.f, 0.f, 0.0f));
    transform = glm::scale(transform, glm::vec3(size, 1.f));
    shader_->setMat4("transform", transform);

    vertexArray_->bind();
    glDrawElements(GL_TRIANGLES, vertexArray_->getIndexBuffer()->getCount(), GL_UNSIGNED_INT, nullptr);
    vertexArray_->unbind();
    shader_->unbind();

    texture->unbind();
}

接著,回到我們老久之前寫的Game

我們要開始渲染了

ResourceManager::loadShader("vShader.glsl", "fShader.glsl", "sprite");
renderer_ = std::make_shared<SpriteRender>(ResourceManager::getShader("sprite"));

glm::mat4 projection = glm::ortho(0.0f, width_, height_, 0.f, -1.0f, 1.0f);


auto& shader = ResourceManager::getShader("sprite");
shader->bind();
shader->setInt("u_Texture", 0);
shader->setMat4("projection", projection);

texture_ = ResourceManager::loadTexture("1.png", "gardevoir");

接著在Game::Render()就可以 Render 了

void Game::Render() {

    renderer_->Draw(texture_, glm::vec2(200.f, 200.f), glm::vec2(100.f, 100.f), -55.f, glm::vec4{1.0f, 1.0f, 1.0f, 1.0f});
}


上一篇
Day 19 Texture & ResourceManager
下一篇
Day 21 ECS intro
系列文
寫遊戲初體驗30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言